/** @file util.hpp Common utility functions */
#pragma once

#include <iostream>
#include <vector>
#include <memory>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>

#include "conf.hpp"
//#include "core/error.hpp"

using std::min;
using std::max;
using std::swap;

//the following are UBUNTU/LINUX ONLY terminal color codes.
#define RESET   "\033[0m"
#define BLACK   "\033[30m"      /* Black */
#define RED     "\033[31m"      /* Red */
#define GREEN   "\033[32m"      /* Green */
#define YELLOW  "\033[33m"      /* Yellow */
#define BLUE    "\033[34m"      /* Blue */
#define MAGENTA "\033[35m"      /* Magenta */
#define CYAN    "\033[36m"      /* Cyan */
#define WHITE   "\033[37m"      /* White */
#define BOLDBLACK   "\033[1m\033[30m"      /* Bold Black */
#define BOLDRED     "\033[1m\033[31m"      /* Bold Red */
#define BOLDGREEN   "\033[1m\033[32m"      /* Bold Green */
#define BOLDYELLOW  "\033[1m\033[33m"      /* Bold Yellow */
#define BOLDBLUE    "\033[1m\033[34m"      /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m"      /* Bold Magenta */
#define BOLDCYAN    "\033[1m\033[36m"      /* Bold Cyan */
#define BOLDWHITE   "\033[1m\033[37m"      /* Bold White */

/** Create a shared smart pointer
 * @param T type of pointer
 * @param args constructor args */
#define MKPTR(T,args...) std::shared_ptr<T>(new T(args))

/** Create a unique smart pointer
 * @param T type of pointer
 * @param args constructor args */
#define MKUPTR(T,args...) std::unique_ptr<T>(new T(args))

/** Convert from degrees to radians
 * @param degrees angle in degrees
 * @return angle in radians */
inline float radians(const float degrees)
{
  return ((2.f*M_PI)/360.f)*degrees;
}

/** Linear interpolation between two quantities
 * @param a fist quantity
 * @param b second quantity
 * @param alpha interpolation constant
 * @return interpolated value */
template <typename T> inline T lerp(const T& a, const T& b, const float x)
{
  return (1.f-x)*a + x*b;
}

/** Convert a value to a string
 * This is not very fast so use it carefully
 * @param v value to convert
 * @return string representation of v */
template <typename T> inline std::string asString(const T& v)
{
  std::stringstream ss;
  ss << v;
  return ss.str();
}

template <> inline std::string asString<std::string>(const std::string& v)
{
  return v;
}
